#pragma once
#include <algorithm>
#include <iostream>



struct vec2f
{
	vec2f() = default;
	vec2f(float x, float y):
		_data{x, y}
	{
	}

	vec2f(const vec2f&) = default;

	void copy(const vec2f& v)
	{
		_data[0] = v.x();
		_data[1] = v.y();
	}


	vec2f operator+(const vec2f& v)
	{
		return vec2f(x() + v.x(), y() + v.y());
	}


	vec2f operator-(const vec2f& v)
	{
		return vec2f(x() - v.x(), y() - v.y());
	}


	vec2f operator*(const vec2f& v)
	{
		return vec2f(x() * v.x(), y() * v.y());
	}

	vec2f operator/(const vec2f& v)
	{
		if(v.x() == 0 || v.y() == 0) return vec2f(0, 0);

		return vec2f(x() / v.x(), y() / v.y());
	}

	float& operator[](const int n)
	{
		switch(n)
		{
			case 0:
				return x();
				break;
			case 1:
				return y();
				break;
			default:
				throw "Erreur";
				return x();
		}
	}

	vec2f& operator +=(vec2f const& v)
	{
	   _data[0] += v.x();
	   _data[1] += v.y();
	   return *this;
	}

	vec2f& operator +=(float a)
	{
	   _data[0] += a;
	   _data[1] += a;
	   return *this;
	}

	vec2f& operator -=(float a)
	{
	   _data[0] -= a;
	   _data[1] -= a;
	   return *this;
	}

	vec2f& operator *=(float a)
	{
		_data[0] *= a;
		_data[1] *= a;
		return *this;
	}

	vec2f& operator /=(float a)
	{
		float inv = 1 / a;
		(*this) *= inv;
		return *this;
	}

	void normalize()
	{
		(*this) /= std::sqrt(std::pow(x(), 2.0) + std::pow(y(), 2.0));
	}

//	// Pas de possibilité de lecture seule
//	float *data()
//	{
//		return _data;
//	}

	const float* data() const
	{
		return _data;
	}

	void exemple_modif_data()
	{
		const float* f = data();
		float* f2 = const_cast<float *>(f);
		f2[0] = 3;
	}

	const float& x() const
	{
		std::cerr << "Vec2f: constant access request;" << std::endl;
		return _data[0];
	}
	const float& y() const
	{
		std::cerr << "Vec2f: constant access request;" << std::endl;
		return _data[1];
	}

	void setx(float x)
	{
		_data[0] = x;
	}
	void sety(float y)
	{
		_data[1] = y;
	}


	float& x()
	{
		std::cerr << "Vec2f: write access request;" << std::endl;
		return _data[0];
	}

	float& y()
	{
		std::cerr << "Vec2f: write access request;" << std::endl;
		return _data[1];
	}

	vec2f div(const float& diviseur, bool non_zero = true)
	{
		// diviseur = 2; // ne marche pas car const
		vec2f v(*this);
		if(non_zero)
		{
			v.x() = (const float) v.x() / diviseur;
			v.y() = (const float) v.y() / diviseur;
		}

		return v;
	}

	private:
		float _data[2];
};


struct vec3f
{
	vec3f(const vec3f&) = default;

	vec3f(float x = 0, float y = 0, float z = 0):
		x(x),
		y(y),
		z(z)
	{

	}

	float x = 0; //Pour constructeur par défault
	float y = 0;
	float z = 0;
};
